﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace MattDotson.GlobalToolkit
{
    /// <summary>
    /// Default implementation of a currency provider.
    /// </summary>
    public class DefaultCurrencyProvider : ICurrencyProvider
    {
        private static object syncRoot = new object();
        private static Dictionary<string, CurrencyInfo> isoMap;

        private static void PreloadCurrencies()
        {
            if (null == isoMap)
            {
                lock (syncRoot)
                {
                    if (null == isoMap)
                    {
                        CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
                        isoMap = new Dictionary<string, CurrencyInfo>(cultures.Length);

                        foreach (CultureInfo culture in cultures)
                        {
                            RegionInfo region = new RegionInfo(culture.LCID);
                            if (false == isoMap.ContainsKey(region.ISOCurrencySymbol))
                            {
                                string isoSymbol = String.Intern(region.ISOCurrencySymbol);
                                string symbol = String.Intern(region.CurrencySymbol);
                                string englishName = String.Intern(region.CurrencyEnglishName);

                                CurrencyInfo currInfo = new CurrencyInfo(isoSymbol, symbol, englishName, culture.NumberFormat.CurrencyDecimalDigits);
                                isoMap.Add(region.ISOCurrencySymbol, currInfo);
                            }
                        }
                    }
                }
            }
        }

        #region ICurrencyProvider Members

        /// <summary>
        /// Returns information about all known currencies.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<CurrencyInfo> GetCurrencies()
        {
            PreloadCurrencies();

            return isoMap.Values.ToList();
        }

        /// <summary>
        /// Finds the currency with the specified ISO 4217 code.
        /// </summary>
        /// <param name="isoCode">The iso code.</param>
        /// <returns>
        /// An instance of a <see cref="CurrencyInfo"/> if the currency is known; otherwise null.
        /// </returns>
        public CurrencyInfo GetCurrencyInfo(string isoCode)
        {
            PreloadCurrencies();
            CurrencyInfo val;
            if (isoMap.TryGetValue(isoCode, out val))
            {
                return val;
            }

            return null;
        }

        #endregion
    }
}
